package com.neusoft.databus.core.service.impl;

import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

import javax.persistence.EntityNotFoundException;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.querydsl.QPageRequest;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import com.excel.poi.ExcelBoot;
import com.excel.poi.entity.ErrorEntity;
import com.excel.poi.function.ExportFunction;
import com.excel.poi.function.ImportFunction;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.neusoft.bizcore.common.utils.DateUtil;
import com.neusoft.bizcore.web.dto.result.ResultDTO;
import com.neusoft.bizcore.web.exception.CustomRuntimeException;
import com.neusoft.bizcore.web.support.Searchable;
import com.neusoft.bizcore.web.utils.ExcelPoiBoot;
import com.neusoft.bizcore.web.utils.ExcelUtil;
import com.neusoft.bizcore.web.utils.JsonUtils;
import com.neusoft.databus.common.bean.CommandBean;
import com.neusoft.databus.common.bean.ResourceBean;
import com.neusoft.databus.common.constant.DatabusErrorCode;
import com.neusoft.databus.common.dto.DictionaryDTO;
import com.neusoft.databus.common.dto.MetricDTO;
import com.neusoft.databus.common.dto.MetricGroupDTO;
import com.neusoft.databus.common.dto.ResourceDTO;
import com.neusoft.databus.common.enums.DictionaryType;
import com.neusoft.databus.common.enums.MetricUsageType;
import com.neusoft.databus.common.model.Gateway;
import com.neusoft.databus.common.model.MetricGroup;
import com.neusoft.databus.common.model.Resource;
import com.neusoft.databus.core.constant.DatabusCoreConstant;
import com.neusoft.databus.core.converter.CommandConverter;
import com.neusoft.databus.core.converter.MetricGroupConverter;
import com.neusoft.databus.core.converter.ResourceConverter;
import com.neusoft.databus.core.event.EventType;
import com.neusoft.databus.core.event.EventWrapper;
import com.neusoft.databus.core.event.ResourceDeleteEvent;
import com.neusoft.databus.core.event.ResourceStatusChangedEvent;
import com.neusoft.databus.core.event.ResourceUpdateEvent;
import com.neusoft.databus.core.repository.MetricGroupRepository;
import com.neusoft.databus.core.repository.ResourceRepository;
import com.neusoft.databus.core.service.DictionaryService;
import com.neusoft.databus.core.service.ExecuteCollectService;
import com.neusoft.databus.core.service.JobExecutableDetermineService;
import com.neusoft.databus.core.service.ResourceService;
import com.neusoft.databus.core.vo.ResourcePortVO;

import lombok.extern.slf4j.Slf4j;

/**
 * 资源服务
 *
 * @author sunchf
 * @date 2018年12月21日 下午4:27:08
 */
@Slf4j
@Service
@Transactional
public class ResourceServiceImpl implements ResourceService {

    @Autowired
    private ResourceRepository resourceRepository;
    @Autowired
    private ResourceConverter resourceConverter;
    @Autowired
    private MetricGroupRepository metricGroupRepository;
    @Autowired
    private MetricGroupConverter metricGroupConverter;
    @Autowired
    private CommandConverter commandConverter;
    @Autowired
    private JobExecutableDetermineService jobExecutableDetermineService;
    @Autowired
    private DictionaryService dictionaryService;
    @Autowired
    private ExecuteCollectService executeCollectService;
    @Autowired
    StringRedisTemplate template;
    @Value("${databus.core.redis.subscribeChannel: channel:databus}")
    private String redisSubscribeChannel;
    //    @javax.annotation.Resource(name = "modelUpdateEventBus")
    //    private AsyncEventBus modelUpdateEventBus;
    //
    //    @PostConstruct
    //    public void init() {
    //        this.modelUpdateEventBus.register(this);
    //    }

    @Override
    public ResourceDTO findById(final long id) {
        try {
            final Resource resouce = this.resourceRepository.getOne(id);
            return this.resourceConverter.toDTO(resouce);
        } catch (final EntityNotFoundException e) {
            throw new CustomRuntimeException(DatabusErrorCode.ERR_CODE_404001, new Object[] {id });
        }

    }

    @Override
    public ResourceDTO findByCode(final String code) {
        final Resource resouce = this.resourceRepository.findByCode(code);
        if (null == resouce) {
            throw new CustomRuntimeException(DatabusErrorCode.ERR_CODE_404001, new Object[] {code });
        }
        return this.resourceConverter.toDTO(resouce);
    }

    @Override
    public List<ResourceDTO> findByGateway(final String gatewayCode) {
        final List<Resource> resources = this.resourceRepository.findByGateway_code(gatewayCode);
        final List<ResourceDTO> DTOs = this.resourceConverter.toListDTO(resources);
        return DTOs;
    }

    @Override
    public List<ResourceDTO> search(final Searchable searchable) {
        final List<Resource> models = this.resourceRepository.search(searchable);
        return this.resourceConverter.toListDTO(models);
    }

    @Override
    public Page<ResourceDTO> search(final Pageable pageable, final Searchable searchable) {
        final Page<Resource> models = this.resourceRepository.search(pageable, searchable);
        return this.resourceConverter.toPageDTO(models);
    }

    @Override
    public ResourceDTO create(final ResourceDTO dto) {
        final Resource model = this.resourceConverter.toModel(dto);
        this.checekByAssociate(model.getCode(), model.getAssociate());
        this.resourceRepository.save(model);
        return this.resourceConverter.toDTO(model);
    }

    @Override
    public ResourceDTO update(final String code, final ResourceDTO dto) {
        Resource model = this.resourceRepository.findByCode(code);
        if (null == model) {
            throw new CustomRuntimeException(DatabusErrorCode.ERR_CODE_404001, new Object[] {code });
        }
        this.checekByAssociate(code, dto.getAssociate());
        dto.setId(model.getId());
        dto.setUpdateTime(new Date());
        model = this.resourceConverter.toModel(dto);
        this.resourceRepository.save(model);
        // 发送资源变更事件
        this.postUpdateEvent(model);
        return this.resourceConverter.toDTO(model);
    }

    @Override
    public void delete(final String code) {

        final Resource model = this.resourceRepository.findByCode(code);
        if (null == model) {
            throw new CustomRuntimeException(DatabusErrorCode.ERR_CODE_404001, new Object[] {code });
        }
        // 发送资源删除事件
        this.postDeleteEvent(model);
        this.resourceRepository.delete(model);
    }

    @Override
    public void enable(final String code) {
        final Resource model = this.resourceRepository.findByCode(code);
        if (null == model) {
            throw new CustomRuntimeException(DatabusErrorCode.ERR_CODE_404001, new Object[] {code });
        }
        model.setDisabled(false);
        model.setUpdateTime(new Date());
        this.resourceRepository.save(model);
        // 发送状态变更事件
        this.postStatusChangedEvent(model);
    }

    @Override
    public void disable(final String code) {
        final Resource model = this.resourceRepository.findByCode(code);
        if (null == model) {
            throw new CustomRuntimeException(DatabusErrorCode.ERR_CODE_404001, new Object[] {code });
        }
        model.setDisabled(true);
        model.setUpdateTime(new Date());
        this.resourceRepository.save(model);
        // 发送状态变更事件
        this.postStatusChangedEvent(model);
    }

    @Override
    public ResourceDTO bind(final Long id, final List<Long> groupIdList) {
        if (groupIdList.size() > 2) {
            throw new CustomRuntimeException(DatabusErrorCode.ERR_CODE_406110);
        }
        final Resource model = this.resourceRepository.getOne(id);
        if (null == model) {
            throw new CustomRuntimeException(DatabusErrorCode.ERR_CODE_404001, new Object[] {id });
        }
        final Map<String, String> oldMetricGroups = new HashMap<>();
        model.getMetricGroups().forEach(g -> {
            oldMetricGroups.put(g.getCode(), g.getName());
        });
        model.getMetricGroups().clear();
        groupIdList.stream().map(i -> {
            final MetricGroup metricGroup = this.metricGroupRepository.getOne(i);
            return metricGroup;
        }).filter(g -> null != g).forEach(model.getMetricGroups()::add);

        if ((model.getMetricGroups().stream().filter(it -> it.getUsageType().equals(MetricUsageType.COLLECT))
                .count() > 1)
                || (model.getMetricGroups().stream().filter(it -> it.getUsageType().equals(MetricUsageType.CONTROL))
                        .count() > 1)) {
            throw new CustomRuntimeException(DatabusErrorCode.ERR_CODE_406110);
        }

        model.setUpdateTime(new Date());
        this.resourceRepository.save(model);
        return this.resourceConverter.toDTO(model);
    }

    @Override
    public ResourceDTO bind(final String code, final List<String> groupCodeList) {
        if ((groupCodeList.size() > 2)) {
            throw new CustomRuntimeException(DatabusErrorCode.ERR_CODE_406110);
        }
        final Resource model = this.resourceRepository.findByCode(code);
        if (null == model) {
            throw new CustomRuntimeException(DatabusErrorCode.ERR_CODE_404001, new Object[] {code });
        }
        model.getMetricGroups().clear();
        groupCodeList.stream().map(c -> {
            final MetricGroup metricGroup = this.metricGroupRepository.findByCode(c);
            return metricGroup;
        }).filter(g -> null != g).forEach(model.getMetricGroups()::add);

        if ((model.getMetricGroups().stream().filter(it -> it.getUsageType().equals(MetricUsageType.COLLECT))
                .count() > 1)
                || (model.getMetricGroups().stream().filter(it -> it.getUsageType().equals(MetricUsageType.CONTROL))
                        .count() > 1)) {
            throw new CustomRuntimeException(DatabusErrorCode.ERR_CODE_406110);
        }

        model.setUpdateTime(new Date());
        this.resourceRepository.save(model);
        return this.resourceConverter.toDTO(model);
    }

    @Override
    public ResultDTO<CommandBean> collect(String code) throws Exception {
        return this.collect(code, null);
    }

    @Override
    public ResultDTO<CommandBean> collect(final String code, Map<String, Object> params) throws Exception {
        if (!this.jobExecutableDetermineService.canExecute()) {
            throw new CustomRuntimeException(DatabusErrorCode.ERR_CODE_400003, new Object[] {"core" });
        }
        final Resource r = this.resourceRepository.findByCode(code);
        if ((null == r)) {
            throw new CustomRuntimeException(DatabusErrorCode.ERR_CODE_404001, new Object[] {code });
        }
        if ((null == r.getGateway())) {
            throw new CustomRuntimeException(DatabusErrorCode.ERR_CODE_406114);
        }
        if ((r.getMetricGroups().stream().filter(it -> it.getUsageType().equals(MetricUsageType.COLLECT))
                .count() == 0)) {
            throw new CustomRuntimeException(DatabusErrorCode.ERR_CODE_406115);
        }
        final ResourceDTO resourceDTO = this.resourceConverter.toDTO(r);

        if (null != params) {
            if (StringUtils.isEmpty(resourceDTO.getConfig())) {
                resourceDTO.setConfig("");
            }
            final Map<String, Object> config = JsonUtils.jsonToMap(resourceDTO.getConfig());
            params.entrySet().forEach(entry -> {
                config.put(entry.getKey(), entry.getValue());
            });

            resourceDTO.setConfig(JsonUtils.pojoToJson(config));
        }

        final MetricGroup metricGroup = r.getMetricGroups().stream()
                .filter(it -> it.getUsageType().equals(MetricUsageType.COLLECT)).findFirst().get();
        if ((metricGroup.getMetrics() == null) || (metricGroup.getMetrics().size() == 0)) {
            throw new CustomRuntimeException(DatabusErrorCode.ERR_CODE_406116);
        }
        final MetricGroupDTO metricGroupDTO = this.metricGroupConverter.toDTO(metricGroup);
        resourceDTO.getMetricGroups().clear();
        resourceDTO.getMetricGroups().add(metricGroupDTO);

        final CommandBean commandBean = this.commandConverter.toCommand(resourceDTO);
        commandBean.setAsync(false);
        commandBean.setForTest(true);
        commandBean.setBeginTime(new Date());

        try {
            if (ResourceServiceImpl.log.isDebugEnabled()) {
                ResourceServiceImpl.log.debug("开始执行手动采集，{}:{}个指标", commandBean.getResourceBean().get(0).getName(),
                        commandBean.getResourceBean().get(0).getMetrics().size());
            }
            final ResultDTO<CommandBean> response = this.executeCollectService.collect(commandBean,
                    commandBean.getGatewayIdentifier());
            if (ResourceServiceImpl.log.isDebugEnabled()) {
                final ResourceBean resourceBean = response.getData().getResourceBean().get(0);
                ResourceServiceImpl.log.debug("手动采集执行完成，{}:{}个采集值,{}个解析值", resourceBean.getName(),
                        resourceBean.getMetrics().stream().filter(it -> it.isExecutedSuccess()).count(),
                        resourceBean.getMetrics().stream().filter(it -> it.isParseSuccess()).count());
            }

            response.getData().setEndTime(new Date());
            return response;

        } catch (final Exception e) {
            if (!(e instanceof CustomRuntimeException)) {
                ResourceServiceImpl.log.error(e.getMessage(), e);
            }
            throw e;
        }
    }

    @Override
    public ResultDTO<CommandBean> control(final String code, final String metric) throws Exception {
        if (!this.jobExecutableDetermineService.canExecute()) {
            throw new CustomRuntimeException(DatabusErrorCode.ERR_CODE_400003, new Object[] {"core" });
        }
        final Resource r = this.resourceRepository.findByCode(code);
        if ((null == r)) {
            throw new CustomRuntimeException(DatabusErrorCode.ERR_CODE_404001, new Object[] {code });
        }
        if ((null == r.getGateway())) {
            throw new CustomRuntimeException(DatabusErrorCode.ERR_CODE_406114);
        }

        if ((r.getMetricGroups().stream().filter(it -> MetricUsageType.CONTROL.equals(it.getUsageType()))
                .count() == 0)) {
            throw new CustomRuntimeException(DatabusErrorCode.ERR_CODE_406116);
        }

        final ResourceDTO resourceDTO = this.resourceConverter.toDTO(r);
        final Optional<MetricGroup> optional = r.getMetricGroups().stream()
                .filter(it -> MetricUsageType.CONTROL.equals(it.getUsageType())).findFirst();
        final MetricGroupDTO metricGroupDTO = this.metricGroupConverter.toDTO(optional.get(), false);
        final Optional<MetricDTO> metricDTO = metricGroupDTO.getMetrics().stream()
                .filter(it -> it.getCode().equals(metric)).findFirst();

        if (!metricDTO.isPresent()) {
            throw new CustomRuntimeException(DatabusErrorCode.ERR_CODE_406117);
        }
        metricGroupDTO.getMetrics().clear();
        metricGroupDTO.getMetrics().add(metricDTO.get());
        resourceDTO.getMetricGroups().clear();
        resourceDTO.getMetricGroups().add(metricGroupDTO);

        final CommandBean commandBean = this.commandConverter.toCommand(resourceDTO);
        commandBean.setAsync(false);
        commandBean.setForTest(true);
        commandBean.setBeginTime(new Date());

        try {
            if (ResourceServiceImpl.log.isDebugEnabled()) {
                ResourceServiceImpl.log.debug("开始执行手动控制,{}", commandBean);
            }
            final ResultDTO<CommandBean> response = this.executeCollectService.control(commandBean,
                    commandBean.getGatewayIdentifier());
            if (ResourceServiceImpl.log.isDebugEnabled()) {
                ResourceServiceImpl.log.debug("手动控制执行完成,{}", response.getData().getResourceBean().get(0).getMetrics()
                        .stream().filter(it -> it.isExecutedSuccess()).count());
            }

            response.getData().setEndTime(new Date());

            return response;

        } catch (final Exception e) {
            ResourceServiceImpl.log.error(e.getMessage(), e);
            throw e;
        }
    }

    /**
     * 发送资源删除事件 <br>
     * 只可能影响资源任务，批处理任务不受影响
     *
     * @param resource
     */
    private void postDeleteEvent(final Resource model) {
        final Gateway gateway = model.getGateway();
        if ((null != gateway) && !gateway.isDisabled() && !gateway.isBatched() && !model.isDisabled()) {
            final ResourceDeleteEvent event = new ResourceDeleteEvent();
            event.setGateway(gateway.getCode());
            event.setResource(model.getCode());
            //this.modelUpdateEventBus.post(event);
            this.template.convertAndSend(this.redisSubscribeChannel,
                    JsonUtils.pojoToJson(new EventWrapper(EventType.resourceDelete, JsonUtils.pojoToJson(event))));

        }
    }

    /**
     * 发送资源变更事件 <br>
     * 挂载网关、更换网关、解除网关，这3种情况可能要更新定时任务 <br>
     * 1，挂载网关：如果网关是批处理任务，网关批处理任务会在运行时检测，不发送事件 <br>
     * 2，更换网关（或网关未改变）：原网关已未知，如果原网关是批处理任务，同上。否则，根据网关状态和资源状态，发送事件。 <br>
     * 3，解除网关：原网关已未知，网关批处理任务会在运行时检测，或资源任务会在运行时检测，不发送事件 <br>
     *
     * @param resource
     */
    private void postUpdateEvent(final Resource model) {

        final Gateway gateway = model.getGateway();
        if ((null == gateway) || gateway.isDisabled() || gateway.isBatched() || model.isDisabled()) {
            return;
        }
        final ResourceUpdateEvent event = new ResourceUpdateEvent();
        event.setResource(model.getCode());
        event.setGateway(gateway.getCode());
        event.setInterval(model.getExecutionCycle());
        //this.modelUpdateEventBus.post(event);
        this.template.convertAndSend(this.redisSubscribeChannel,
                JsonUtils.pojoToJson(new EventWrapper(EventType.resourceUpdate, JsonUtils.pojoToJson(event))));
    }

    /**
     * 发送资源状态变更事件 <br>
     * 未挂载网关、网关已停用、网关设置为批处理，在这三种情况下，资源的状态改变不需要处理资源的定时任务 <br>
     *
     * @param resource
     */
    private void postStatusChangedEvent(final Resource resource) {
        final Gateway gateway = resource.getGateway();
        // 未挂载网关、网关已停用、网关设置为批处理，在这三种情况下，资源的状态改变不需要处理资源的定时任务
        if ((null != gateway) && !gateway.isDisabled() && !gateway.isBatched()) {
            final ResourceStatusChangedEvent event = new ResourceStatusChangedEvent();
            event.setGateway(gateway.getCode());
            event.setResource(resource.getCode());
            event.setDisabled(resource.isDisabled());
            event.setInterval(resource.getExecutionCycle());
            //this.modelUpdateEventBus.post(event);
            this.template.convertAndSend(this.redisSubscribeChannel,
                    JsonUtils.pojoToJson(
                            new EventWrapper(EventType.resourceStatusChanged, JsonUtils.pojoToJson(event))));
        }

    }

    /**
     * 根据子系统设备编码查询databus设备信息
     */
    @Override
    public ResourceDTO findByAssociate(final String associate) {
        if (StringUtils.isNotEmpty(associate)) {
            final List<Resource> resources = this.resourceRepository.findByAssociate(associate);
            if (resources.size() > 0) {
                final Resource model = resources.get(0);
                return this.resourceConverter.toSelfDTO(model);
            } else {
                throw new CustomRuntimeException(DatabusErrorCode.ERR_CODE_404001, new Object[] {associate });
            }
        }
        throw new CustomRuntimeException(DatabusErrorCode.ERR_CODE_404001, new Object[] {associate });
    }

    private void checekByAssociate(final String code, final String associate) {
        if (StringUtils.isEmpty(associate)) {
            return;
        }
        final List<Resource> resources = this.resourceRepository.findByAssociate(associate);
        final long size = resources.stream()
                .filter(r -> !(r.getCode().equals(code)) && r.getAssociate().equals(associate)).count();
        if (size > 0) {
            throw new CustomRuntimeException(DatabusErrorCode.ERR_CODE_406119);
        }
    }

    @Override
    public void importTpl(final MultipartFile excel) {
        final StringBuffer errmsg = new StringBuffer();
        final List<Resource> listCache = Lists.newArrayList();
        try {
            try {
                ExcelPoiBoot.ImportBuilder(excel.getInputStream(), ResourcePortVO.class)
                        .importExcel(new ImportFunction<ResourcePortVO>() {
                            @Override
                            public void onProcess(final int sheetIndex, final int rowIndex,
                                    final ResourcePortVO portVO) {
                                final Resource resource = ResourceServiceImpl.this.resourceConverter.toModel(portVO);
                                listCache.add(resource);
                            }

                            @Override
                            public void onError(final ErrorEntity errorEntity) {
                                ResourceServiceImpl.log.error("资源导入错误：{}", JsonUtils.pojoToJson(errorEntity));
                                errmsg.append(errorEntity.getErrorMessage()).append("\n");
                            }
                        });
            } catch (final IOException e) {
                throw new CustomRuntimeException(DatabusErrorCode.ERR_CODE_406112, new Object[] {e.getMessage() });
            }
            errmsg.append(this.excelImport(listCache));
        } finally {
            listCache.clear();
        }
        if (StringUtils.isNotBlank(errmsg.toString())) {
            throw new CustomRuntimeException(DatabusErrorCode.ERR_CODE_406112, new Object[] {errmsg.toString() });
        }

    }

    private String excelImport(final List<Resource> resources) {
        final StringBuffer reusltMessage = new StringBuffer();
        final List<String> associates = resources.stream().filter(r -> StringUtils.isNotBlank(r.getAssociate()))
                .map(r -> r.getAssociate()).collect(Collectors.toList());
        final long distinctSize = associates.stream().distinct().count();
        if (distinctSize != associates.size()) {
            reusltMessage.append("导入的数据中存在子系统设备编码相同的设备，请修改后导入");
            return reusltMessage.toString();
        } else {
            resources.stream().forEach(r -> {
                int size = 0;
                if (StringUtils.isNotBlank(r.getAssociate())) {
                    size = this.resourceRepository.findByAssociate(r.getAssociate()).size();
                }
                if (size <= 0) {
                    this.resourceRepository.save(r);
                } else {
                    reusltMessage.append(r.getName()).append("的子系统设备编码系统中已存在").append(";");
                }
            });
        }
        return reusltMessage.toString();
    }

    @Override
    public Map<String, List<Long>> distribution() {
        return this.resourceRepository.distribution();
    }

    @Override
    public SXSSFWorkbook getTpl() {
        final String sheetName = DatabusCoreConstant.TPL_NAME_RESOURCE;
        final Map<Integer, String[]> dropDowns = Maps.newHashMap();
        final List<DictionaryDTO> dictionaries = this.dictionaryService
                .findByDictionaryTypeAndParentIsNotNull(DictionaryType.resource);
        final String[] dictionaryDropDown = new String[dictionaries.size()];
        for (int i = 0; i < dictionaries.size(); i++) {
            final DictionaryDTO dictionary = dictionaries.get(i);
            dictionaryDropDown[i] = dictionary.getCode() + DatabusCoreConstant.DICTIONARY_SPLITOR
                    + dictionary.getText();
        }
        dropDowns.put(1, dictionaryDropDown);

        final SXSSFWorkbook workbook = ExcelUtil.createExcelTemplate(sheetName, DatabusCoreConstant.RESOURCE_TPL_COLUMN,
                dropDowns);
        return workbook;
    }

    @Override
    public void export(final Searchable searchable, final Pageable pageable, final HttpServletResponse response) {
        final StringBuffer fileName = new StringBuffer("设备");
        fileName.append(DatabusCoreConstant.EXPORT_SPLITOR)
                .append(DateUtil.currentTimestamp2String(DateUtil.PATTERN_NULL_CONN));
        ExcelBoot.ExportBuilder(response, fileName.toString(), ResourcePortVO.class)
                .exportMultiSheetResponse(searchable, new ExportFunction<Searchable, Resource>() {
                    @Override
                    public List<Resource> pageQuery(final Searchable searchable, final int pageNum,
                            final int pageSize) {
                        final QPageRequest qPageRequest = new QPageRequest(pageNum - 1, pageSize);
                        final Page<Resource> models = ResourceServiceImpl.this.resourceRepository.search(qPageRequest,
                                searchable);
                        return models.getContent();
                    }

                    @Override
                    public ResourcePortVO convert(final Resource model) {
                        return ResourceServiceImpl.this.resourceConverter.toVO(model);
                    }
                });

    }

    @Override
    public List<ResourceDTO> findCollectedResources() {
        final List<Resource> resources = this.resourceRepository.findCollectedResources();
        final List<ResourceDTO> DTOs = this.resourceConverter.toListDTO(resources);
        return DTOs;
    }

    @Override
    public boolean isExisted(String code) {
        final Resource resouce = this.resourceRepository.findByCode(code);
        if (null == resouce) {
            return false;
        } else {
            return true;
        }

    }

}
